-------------------------------------------------------------------------------
-- datapath_rtl.vhd
-------------------------------------------------------------------------------
--
-- This file is part of SKUMLI.
-- Copyright (C) 2011 Davide Giuseppe Monaco (black.ralkass@gmail.com)
--
-- SKUMLI is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- SKUMLI is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with SKUMLI.  If not, see <http://www.gnu.org/licenses/>.
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.alu_pack.all;
use work.mem_hierarchy_pack.all;
use work.mux_pack.all;
use work.regfile_pack.all;
use work.register_pack.all;
use work.sign_ext_pack.all;
-------------------------------------------------------------------------------
architecture schematic of datapath is

  signal tg_dout      : std_logic_vector(31 downto 0);
  signal alu_dout     : std_logic_vector(31 downto 0);
  signal pc_din       : std_logic_vector(31 downto 0);
  signal pc_we        : std_logic;
  signal pc_dout      : std_logic_vector(31 downto 0);
  signal alu_zero     : std_logic;
  signal alu_out_dout : std_logic_vector(31 downto 0);
  signal opd_b_dout   : std_logic_vector(31 downto 0);
  signal md_dout      : std_logic_vector(31 downto 0);
  signal rf_din       : std_logic_vector(31 downto 0);
  signal ir_dout      : std_logic_vector(31 downto 0);
  signal operand_a    : std_logic_vector(31 downto 0);
  signal operand_b    : std_logic_vector(31 downto 0);
  signal ext_imm      : std_logic_vector(31 downto 0); -- ext_sign( IR(15:0) )
  signal plus_four    : std_logic_vector(31 downto 0); -- fixed 0x00000004
  signal shift_imm    : std_logic_vector(31 downto 0); -- ext_imm << 2
  signal opd_a_dout   : std_logic_vector(31 downto 0);
  signal rf_dout1     : std_logic_vector(31 downto 0);
  signal rf_dout0     : std_logic_vector(31 downto 0);
  signal m_rd_dout    : std_logic_vector(4 downto 0);  -- RD/RT
  signal jd_dout      : std_logic_vector(31 downto 0); -- jump destination

  signal ca_addr      : std_logic_vector(31 downto 0); -- 
  signal ca_dout      : std_logic_vector(31 downto 0); -- 
  signal cc_addr      : std_logic_vector(31 downto 0); -- cc address (from mux)
  signal cc_dout      : std_logic_vector(31 downto 0); -- cc data out

  signal m_ca_addr_sel    : std_logic_vector(1 downto 0);

  signal none         : std_logic_vector(31 downto 0);

begin -- schematic
-------------------------------------------------------------------------------
  opcode    <= ir_dout(31 downto 26);
  pc_we     <= ((alu_zero xnor cu_zero) and branch) or pc_we_s;
  plus_four <= "00000000000000000000000000000100";
  none      <= (others => '0');

  -- jd_dout = first 4 bits from PC, then 28 bits from shifting ir_dout
  jd_dout(31 downto 28)  <= pc_dout(31 downto 28);
  jd_dout(27 downto  2)  <= ir_dout(25 downto  0);
  jd_dout( 1 downto  0)  <= (others => '0');

  shift_imm(31 downto 2) <= ext_imm(29 downto 0);
  shift_imm(1 downto 0)  <= (others => '0');

  m_ca_addr_sel(1) <= ((alu_zero xnor cu_zero) and branch) or ca_addr_sel(1);
  m_ca_addr_sel(0) <= ca_addr_sel(0);

  MUX_PC_DIN : mux4x1
    port map (
      m_pc_din_sel,   -- sel
      tg_dout,        -- a
      alu_dout,       -- b
      jd_dout,        -- c
      none,           -- d, is not used
      pc_din          -- dout
    );

  PC : reg
    port map (
      clk, rst,
      pc_we,          -- we
      pc_din,         -- din
      pc_dout         -- dout
    );

  MUX_CA_ADDR : mux4x1
    port map (
      m_ca_addr_sel,  -- sel
      pc_dout,        -- a
      none,           -- b
      tg_dout,        -- c
      jd_dout,        -- d
      ca_addr         -- dout
    );

  CURR_ADDR : reg
    port map (
      clk, rst,
      ca_we,          -- we
      ca_addr,        -- din
      ca_dout         -- dout
    );

  MUX_CC_ADDR : mux2x1
    port map (
      m_cc_addr_sel, -- sel
      ca_dout,       -- a
      alu_out_dout,  -- b
      cc_addr        -- dout
    );

  MEM_H : mem_hierarchy
    port map (
      clk, rst,
      cc_rw,      -- rw
      cc_cs,      -- cs
      cc_addr,    -- addr
      opd_b_dout, -- din
      cc_rdy,     -- rdy
      cc_dout     -- dout
    );

  MEM_DATA : reg
    port map (
      clk, rst,
      md_we,          -- we
      cc_dout,        -- din
      md_dout         -- dout
    );

  MUX_DATA : mux2x1
    port map (
      m_data_sel,     -- sel
      md_dout,        -- a
      alu_out_dout,   -- b
      rf_din          -- dout
    );

  IR : reg
    port map (
      clk, rst,
      ir_we,          -- we
      cc_dout,        -- din
      ir_dout         -- dout
    );

  ALU_OUT : reg
    port map (
      clk, rst,
      alu_out_we,     -- we
      alu_dout,       -- din
      alu_out_dout    -- dout
    );

  TARGET : reg
    port map (
      clk, rst,
      tg_we,          -- we
      alu_dout,       -- din
      tg_dout         -- dout
    );

  ALU_INST : alu
    port map (
      operand_a,      -- a
      operand_b,      -- b
      alu_op,         -- op
      alu_zero,       -- zero
      alu_dout        -- dout
    );

  MUX_OPD_B : mux4x1
    port map (
      m_opd_b_sel,    -- sel
      opd_b_dout,     -- a
      ext_imm,        -- b
      plus_four,      -- c
      shift_imm,      -- d
      operand_b       -- dout
    );

  SIGN_EXT : signext
    port map (
      ir_dout(15 downto 0), -- din
      ext_imm
    );
    
  MUX_OPD_A : mux2x1
    port map (
      m_opd_a_sel,    -- sel
      pc_dout,        -- a
      opd_a_dout,     -- b
      operand_a       -- dout
    );

  OPD_B : reg
    port map (
      clk, rst,
      opd_b_we,       -- we
      rf_dout1,       -- din
      opd_b_dout      -- dout
    );

  OPD_A : reg
    port map (
      clk, rst,
      opd_a_we,       -- we
      rf_dout0,       -- din
      opd_a_dout      -- dout
    );

  REGISTER_FILE : regfile
    port map (
      clk, rst,
      rf_we,                  -- we
      ir_dout(25 downto 21),  -- s
      ir_dout(20 downto 16),  -- t
      m_rd_dout,              -- d
      rf_din,                 -- din
      rf_dout0,               -- dout0
      rf_dout1                -- dout1
    );

  MUX_RD : mux2x1
    generic map ( 5 )
    port map (
      m_rd_sel,               -- sel
      ir_dout(20 downto 16),  -- a
      ir_dout(15 downto 11),  -- b
      m_rd_dout               -- dout
    );
-------------------------------------------------------------------------------
end schematic;
